/*
   Copyright 2009 Abdulla Abdurakhmanov (abdulla@latestbit.com)
   Original sources are available at www.latestbit.com

   Licensed under the Apache License, Version 2.0 (the "License");
   you may not use this file except in compliance with the License.
   You may obtain a copy of the License at

       http://www.apache.org/licenses/LICENSE-2.0

   Unless required by applicable law or agreed to in writing, software
   distributed under the License is distributed on an "AS IS" BASIS,
   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   See the License for the specific language governing permissions and
   limitations under the License.
*/

package org.latestbit.smartobjects;

import java.io.IOException;
import java.net.URISyntaxException;

import org.latestbit.smartobjects.coders.*;
import org.latestbit.smartobjects.core.*;
import org.latestbit.smartobjects.encrypters.IDataEncrypterFactory;
import org.latestbit.smartobjects.exceptions.*;
import org.latestbit.smartobjects.network.*;
import org.latestbit.smartobjects.utils.*;

/**
 * ISmartBus is a holder contains shared resources and configurations, 
 * and uses in many others SmartObject classes & interfaces.
 * With this object you can redefine/reconfigure coding, networking and
 * encrypting implementation/algorithms to another's (or to your own implementations).
 * For example, you can configure encrypting algorithms, choose connection mode 
 * or implement your own thread pool. Of course usually this is not required and 
 * you can create ISmartBus with default environment. 
 * Default implementation of ISmartBus is SmartBus. You can create the interface implementation as:
 * <pre>
 * 
 *  // Importing
 *  import org.latestbit.smartobjects.*;
 *  
 *  ...
 *  
 *  // Creating
 *  ISmartBus bus = new SmartBus();
 * 
 *  // Usage
 *  MyInterfaceClient client = new MyInterfaceClient ( );
 *  client.resolve ( bus, ... );
 *  
 * </pre> 
 * @see SmartBus
 * @author abdulla-a
 *
 **/
public interface ISmartBus extends IDestroyable {
	
	/**
	 * Creates new data types coder instance
	 * @return Data Types Coder
	 */
	public IDataTypesCoder createDataTypesCoder();
		

	/**
	 * Gets sequence generator of long values (globally defined for this bus instance)
	 * @return Sequence generator of long values
	 */
	public SequenceGenerator getSequenceGenerator();

	/**
	 * Gets current managed network implementation
	 * @return Managed Network
	 */
	public IManagedNetwork getManagedNetwork();
	
	/**
	 * Changes default managed network implementation to another (your own implementation)
	 * @param network
	 */
	public void setManagedNetwork(IManagedNetwork network);

	/**
	 * Connection mode when resolving remote SmartObjects. 
	 * @author abdulla-a
	 */
	public enum ConnectMode {
		/**
		 * Waiting to connect when resolving IRemoteSmartObject
		 */
		SYNC_CONNECT_MODE,
		/**
		 * Start asynchronously connecting to remote side. Application will receive resolved status 
		 * with a notification to specified handler. 
		 * @see IRemoteSmartObject#addAvailabilityListener(IRemoteSmartObjectAvailabilityListener)  
		 */
		ASYNC_CONNECT_MODE
	}
	
	/**
	 * Sets the current connection mode (for resolving remote SmartObjects).
	 * Default is SYNC_CONNECT_MODE
	 * @param mode a new connection mode
	 */
	public void setConnectMode(ConnectMode mode);
	
	/**
	 * Gets the current connection mode
	 * Default is SYNC_CONNECT_MODE
	 * @return current connection mode
	 */
	public ConnectMode getConnectMode();
	
	/**
	 * Sets timeout to connect to remote side.
	 * <i>This timeout is affected only for SYNC_CONNECT_MODE</i>
	 * @see ISmartBus.ConnectMode
	 * @see #setConnectMode(ConnectMode)  
	 * @param seconds timeout to connect (in seconds)
	 */
	public void setSyncConnectTimeout(long seconds);

	/**
	 * Gets the current timeout to connect to remote side.
	 * <i>This timeout is affected only for SYNC_CONNECT_MODE</i>
	 * @see ISmartBus.ConnectMode
	 * @see #setConnectMode(ConnectMode)  
	 * @return timeout to connect (in seconds)
	 */	
	public long getSyncConnectTimeout();

	/**
	 * Gets shared thread pool
	 * @return thread pool
	 */
	public IThreadPool getThreadPool();

	/**
	 * Gets access to registry of server instances of SmartObjects (skeletons & implementations). 
	 * The registry automatically contains only SmartObjects created & returned from 
	 * another SmartObject implementations and only if these SmartObjects isn't published manually  
	 * @return registry of server instances
	 */
	public IServerInstancesRegistry getServerInstancesRegistry();
	
	/**
	 * Creates (or selects already created) SmartBusClient instance
	 * @param location endpoint location
	 * @return SmartBusClient
	 * @throws IncorrectURIException
	 * @throws IOException
	 * @throws InterruptedException
	 * @throws SmartBusSystemException 
	 */
	SmartBusClient selectBusClient(IEndpointLocation location)
		throws IncorrectURIException, IOException, InterruptedException, SmartBusSystemException;

	/**
	 * Returns unused SmartBusClient instance to bus
	 * @param client SmartBusClient
	 */
	void returnBusClient(SmartBusClient client);
	
	/**
	 * Creates or (selects already created) SmartBusServer instance 
	 * @param location endpoint location
	 * @return SmartBusClient
	 * @throws IncorrectURIException
	 * @throws IOException
	 * @throws SmartBusSystemException 
	 * @throws InterruptedException
	 */
	SmartBusServer selectBusServer(IEndpointLocation location)
		throws IncorrectURIException, IOException, SmartBusSystemException;

	/**
	 * Returns unused SmartBusServer to bus
	 * @param server SmartBusServer
	 */	
	void returnBusServer(SmartBusServer server);	
	
	/**
	 * Gets the current coordinators factory
	 * @return coordinators factory implementation
	 */
	IEndpointCoordinatorFactory getCoordinatorFactory();
	
	/**
	 * Sets a new/custom coordinator factory
	 * @param factory coordinator factory
	 */
	void setCoordinatorFactory(IEndpointCoordinatorFactory factory);
	
	/**
	 * Gets access to data encrypter factory, which uses all SmartObjects
	 * @return data encrypter factory
	 */
	public IDataEncrypterFactory getDataEncrypterFactory();	

	/**
	 * Sets another implementation of data encrypter factory
	 * @param factory data encrypter factory
	 */
	public void setDataEncrypterFactory(IDataEncrypterFactory factory);

	/**
	 * Sets another implementation of handshake manager factory
	 * @param handshakeManagerFactory IHandshakeManagerFactory implementation 
	 */
	void setHandshakeManagerFactory( IHandshakeManagerFactory handshakeManagerFactory );
	
	/**
	 * Gets handshake manager factory, which uses all connections for handshaking (security/authentication) algorithms
	 * @return current handshake manager factory
	 */
	IHandshakeManagerFactory getHandshakeManagerFactory();
	
	/**
	 * Creates new instance of EndpointLocation
	 * @param referenceURI Reference URI to remote hosts
	 * @throws URISyntaxException Invalid syntax of URI
	 */
	IEndpointLocation createEndpointLocation(String referenceURI) throws URISyntaxException;
}
